<template>
    <DrawerPro
        v-model="open"
        :header="$t('runtime.' + mode)"
        size="large"
        :resource="mode === 'edit' ? runtime.name : ''"
        @close="handleClose"
    >
        <el-form
            ref="runtimeForm"
            label-position="top"
            :model="runtime"
            label-width="125px"
            :rules="rules"
            :validate-on-rule-change="false"
            v-loading="loading"
        >
            <el-form-item :label="$t('commons.table.name')" prop="name">
                <el-input :disabled="mode === 'edit'" v-model="runtime.name"></el-input>
            </el-form-item>
            <el-form-item :label="$t('app.source')" prop="resource">
                <el-radio-group
                    :disabled="mode === 'edit'"
                    v-model="runtime.resource"
                    @change="changeResource(runtime.resource)"
                >
                    <el-radio :value="'appstore'" v-if="!globalStore.isOffLine">
                        {{ $t('menu.apps') }}
                    </el-radio>
                    <el-radio :value="'local'">
                        {{ $t('commons.table.local') }}
                    </el-radio>
                </el-radio-group>
            </el-form-item>
            <div v-if="runtime.resource === 'appstore'">
                <el-form-item :label="$t('app.app')" prop="appID">
                    <el-row :gutter="20">
                        <el-col :span="12">
                            <el-select
                                v-model="runtime.appID"
                                :disabled="mode === 'edit'"
                                @change="changeApp(runtime.appID)"
                                class="p-w-200"
                            >
                                <el-option
                                    v-for="(app, index) in apps"
                                    :key="index"
                                    :label="app.name"
                                    :value="app.id"
                                ></el-option>
                            </el-select>
                        </el-col>
                        <el-col :span="12">
                            <el-select
                                v-model="runtime.version"
                                :disabled="mode === 'edit'"
                                @change="changeVersion()"
                                class="p-w-200"
                            >
                                <el-option
                                    v-for="(version, index) in appVersions"
                                    :key="index"
                                    :label="version"
                                    :value="version"
                                ></el-option>
                            </el-select>
                        </el-col>
                    </el-row>
                </el-form-item>
                <div v-if="initParam">
                    <el-form-item
                        :label="getLabel(formFields['PHP_VERSION'])"
                        :rules="rules.params.PHP_VERSION"
                        v-if="formFields['PHP_VERSION']"
                    >
                        <el-select
                            v-model="runtime.params['PHP_VERSION']"
                            filterable
                            default-first-option
                            @change="changePHPVersion(runtime.params['PHP_VERSION'])"
                        >
                            <el-option
                                v-for="service in formFields['PHP_VERSION'].values"
                                :key="service.label"
                                :value="service.value"
                                :label="service.label"
                            ></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item :label="$t('container.image')" prop="image">
                        <el-input v-model="runtime.image"></el-input>
                    </el-form-item>
                    <el-form-item
                        :label="getLabel(formFields['CONTAINER_PACKAGE_URL'])"
                        :rules="rules.params.CONTAINER_PACKAGE_URL"
                        v-if="runtime.params['PHP_VERSION'] != '5.6.40' && formFields['CONTAINER_PACKAGE_URL']"
                    >
                        <el-select v-model="runtime.source" filterable default-first-option allow-create>
                            <el-option
                                v-for="source in phpSources"
                                :key="source.label"
                                :value="source.value"
                                :label="source.label + ' [' + source.value + ']'"
                            ></el-option>
                        </el-select>
                    </el-form-item>

                    <el-form-item
                        :label="getLabel(formFields['PANEL_APP_PORT_HTTP'])"
                        prop="params.PANEL_APP_PORT_HTTP"
                        v-if="formFields['PANEL_APP_PORT_HTTP']"
                    >
                        <el-input
                            v-model.number="runtime.params['PANEL_APP_PORT_HTTP']"
                            maxlength="15"
                            :disabled="mode == 'edit'"
                        ></el-input>
                    </el-form-item>
                    <el-form-item :label="$t('app.containerName')" prop="params.CONTAINER_NAME">
                        <el-input v-model.trim="runtime.params['CONTAINER_NAME']"></el-input>
                    </el-form-item>
                    <el-form-item :label="$t('website.remark')" prop="remark">
                        <el-input type="textarea" :rows="1" clearable v-model="runtime.remark" />
                    </el-form-item>
                    <el-form-item>
                        <el-alert :title="$t('php.containerConfigHelper')" type="info" :closable="false" />
                    </el-form-item>
                    <el-form-item>
                        <el-alert type="warning" :closable="false">
                            <template #default>
                                <div>
                                    <div>{{ $t('runtime.buildHelper') }}</div>
                                    <span>
                                        {{ $t('runtime.extendHelper') }}
                                    </span>
                                    <span
                                        v-if="!globalStore.isFxplay"
                                        class="custom-link"
                                        @click="openLink(globalStore.docsUrl + '/user_manual/websites/php/#php_1')"
                                    >
                                        {{ $t('php.toExtensionsList') }}
                                    </span>
                                </div>
                            </template>
                        </el-alert>
                    </el-form-item>
                    <el-form-item :label="$t('php.extensions')">
                        <el-select v-model="extensions" @change="changePHPExtension()" clearable>
                            <el-option
                                v-for="(extension, index) in phpExtensions"
                                :key="index"
                                :label="extension.name"
                                :value="extension.extensions"
                            ></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item :label="getLabel(formFields['PHP_EXTENSIONS'])" v-if="formFields['PHP_EXTENSIONS']">
                        <el-select v-model="runtime.params['PHP_EXTENSIONS']" multiple allowCreate filterable>
                            <el-option
                                v-for="service in formFields['PHP_EXTENSIONS'].values"
                                :key="service.label"
                                :value="service.value"
                                :label="service.label"
                            ></el-option>
                        </el-select>
                    </el-form-item>
                </div>
            </div>
            <div v-else>
                <el-form-item>
                    <el-alert type="info" :closable="false">
                        <template #title>
                            <span>
                                {{ $t('runtime.localHelper') }}
                                <el-link
                                    class="ml-1 text-xs"
                                    type="primary"
                                    target="_blank"
                                    :href="globalStore.docsUrl + '/user_manual/websites/php/'"
                                >
                                    {{ $t('commons.button.helpDoc') }}
                                </el-link>
                            </span>
                        </template>
                    </el-alert>
                </el-form-item>
                <el-form-item :label="$t('app.version')" prop="version">
                    <el-input v-model="runtime.version" :placeholder="$t('runtime.versionHelper')"></el-input>
                </el-form-item>
            </div>
        </el-form>
        <template #footer>
            <span>
                <el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
                <el-button type="primary" @click="submit(runtimeForm)" :disabled="loading">
                    {{ $t('commons.button.confirm') }}
                </el-button>
            </span>
        </template>
    </DrawerPro>
</template>

<script lang="ts" setup>
import { App } from '@/api/interface/app';
import { Runtime } from '@/api/interface/runtime';
import { getAppByKey, getAppDetail, searchApp } from '@/api/modules/app';
import { CreateRuntime, GetRuntime, ListPHPExtensions, UpdateRuntime } from '@/api/modules/runtime';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { reactive, ref } from 'vue';
import { getLabel } from '@/utils/util';
import { useGlobalStore } from '@/composables/useGlobalStore';
const { globalStore } = useGlobalStore();

interface OperateRrops {
    id?: number;
    mode: string;
    type: string;
    appID?: number;
}

const open = ref(false);
const apps = ref<App.App[]>([]);
const runtimeForm = ref<FormInstance>();
const loading = ref(false);
const initParam = ref(false);
const mode = ref('create');
const appParams = ref<App.AppParams>();
const appVersions = ref<string[]>([]);
const phpExtensions = ref([]);
const appReq = reactive({
    type: 'php',
    page: 1,
    pageSize: 20,
});
const phpSources = globalStore.isIntl
    ? [
          {
              label: i18n.global.t('runtime.default'),
              value: 'https://deb.debian.org',
          },
          {
              label: i18n.global.t('runtime.xtom'),
              value: 'https://mirrors.xtom.com',
          },
      ]
    : [
          {
              label: i18n.global.t('runtime.ustc'),
              value: 'https://mirrors.ustc.edu.cn',
          },
          {
              label: i18n.global.t('runtime.netease'),
              value: 'https://mirrors.163.com',
          },
          {
              label: i18n.global.t('runtime.aliyun'),
              value: 'https://mirrors.aliyun.com',
          },
          {
              label: i18n.global.t('runtime.tsinghua'),
              value: 'https://mirrors.tuna.tsinghua.edu.cn',
          },
          {
              label: i18n.global.t('runtime.xtomhk'),
              value: 'https://mirrors.xtom.com.hk',
          },
          {
              label: i18n.global.t('runtime.xtom'),
              value: 'https://mirrors.xtom.com',
          },
          {
              label: i18n.global.t('commons.table.default'),
              value: 'https://deb.debian.org',
          },
      ];

const initData = (type: string) => ({
    name: '',
    appDetailID: undefined,
    image: '',
    params: {},
    type: type,
    resource: 'appstore',
    rebuild: false,
    source: phpSources[0].value,
    environments: [],
    remark: '',
});
const extensions = ref();
const formFields = ref();

let runtime = reactive<Runtime.RuntimeCreate>(initData('php'));

const rules = ref<any>({
    name: [Rules.appName],
    resource: [Rules.requiredInput],
    appID: [Rules.requiredSelect],
    version: [Rules.requiredInput, Rules.paramCommon],
    image: [Rules.requiredInput, Rules.imageName],
    source: [Rules.requiredSelect],
    params: {
        PANEL_APP_PORT_HTTP: [Rules.requiredInput, Rules.port],
        PHP_VERSION: [Rules.requiredSelect],
        CONTAINER_PACKAGE_URL: [Rules.requiredSelect],
        CONTAINER_NAME: [Rules.containerName, Rules.requiredInput],
    },
});

const em = defineEmits(['close', 'submit']);

const openLink = (url: string) => {
    window.open(url, '_blank');
};

const handleClose = () => {
    open.value = false;
    em('close', false);
};

const changeResource = (resource: string) => {
    if (resource === 'local') {
        runtime.appDetailID = undefined;
        runtime.version = '';
        runtime.params = {};
        runtime.image = '';
    } else {
        runtime.version = '';
        searchAppList(null);
    }
};

const searchAppList = (appId: number) => {
    searchApp(appReq).then((res) => {
        apps.value = res.data.items || [];
        if (res.data && res.data.items && res.data.items.length > 0) {
            if (appId == null) {
                runtime.appID = res.data.items[0].id;
                getApp(res.data.items[0].key, mode.value);
            } else {
                res.data.items.forEach((item) => {
                    if (item.id === appId) {
                        getApp(item.key, mode.value);
                    }
                });
            }
        }
    });
};

const changeApp = (appId: number) => {
    extensions.value = undefined;
    for (const app of apps.value) {
        if (app.id === appId) {
            initParam.value = false;
            getApp(app.key, mode.value);
            break;
        }
    }
};

const changePHPVersion = (version: string) => {
    runtime.image = '1panel-php-fpm:' + version;
};

const changeVersion = () => {
    loading.value = true;
    initParam.value = false;
    extensions.value = undefined;
    getAppDetail(runtime.appID, runtime.version, 'runtime')
        .then((res) => {
            runtime.appDetailID = res.data.id;
            runtime.image = res.data.image + ':' + runtime.version;
            appParams.value = res.data.params;
            const fileds = res.data.params.formFields;
            formFields.value = {};
            for (const index in fileds) {
                formFields.value[fileds[index]['envKey']] = fileds[index];
                runtime.params[fileds[index]['envKey']] = fileds[index]['default'];
                if (fileds[index]['envKey'] == 'PHP_VERSION') {
                    runtime.image = '1panel-php-fpm:' + fileds[index]['default'];
                }
            }
            initParam.value = true;
        })
        .finally(() => {
            loading.value = false;
        });
};

const getApp = (appkey: string, mode: string) => {
    getAppByKey(appkey).then((res) => {
        appVersions.value = res.data.versions || [];
        if (res.data.versions.length > 0) {
            if (mode === 'create') {
                runtime.version = res.data.versions[0];
                changeVersion();
            } else {
                initParam.value = true;
            }
        }
    });
};

const submit = async (formEl: FormInstance | undefined) => {
    if (!formEl) return;
    await formEl.validate(async (valid) => {
        if (!valid) {
            return;
        }
        try {
            let res;
            if (mode.value == 'create') {
                loading.value = true;
                res = await CreateRuntime(runtime);
                MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
            } else {
                loading.value = true;
                res = await UpdateRuntime(runtime);
                MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
            }
            handleClose();
            em('submit', res.data.id);
        } catch (error) {
        } finally {
            loading.value = false;
        }
    });
};

const getRuntime = async (id: number) => {
    try {
        const res = await GetRuntime(id);
        const data = res.data;
        Object.assign(runtime, {
            id: data.id,
            name: data.name,
            appDetailID: data.appDetailID,
            image: data.image,
            params: data.params,
            type: data.type,
            resource: data.resource,
            appID: data.appID,
            version: data.version,
            rebuild: true,
            source: data.source,
            remark: data.remark,
            versionn: data.version,
        });

        const fileds = data.appParams;
        const forms = {};
        for (const index in fileds) {
            forms[fileds[index].key] = fileds[index];
        }
        formFields.value = forms;
        if (data.params['PHP_EXTENSIONS'] != '') {
            runtime.params['PHP_EXTENSIONS'] = runtime.params['PHP_EXTENSIONS']
                .split(',')
                .filter((item) => item !== '');
        }
        initParam.value = true;
    } catch (error) {}
};

const listPHPExtensions = async () => {
    try {
        const res = await ListPHPExtensions({
            all: true,
            page: 1,
            pageSize: 100,
        });
        phpExtensions.value = res.data.items;
    } catch (error) {}
};

const changePHPExtension = () => {
    if (extensions.value == '') {
        return;
    }
    runtime.params['PHP_EXTENSIONS'] = extensions.value.split(',');
};

const acceptParams = async (props: OperateRrops) => {
    mode.value = props.mode;
    initParam.value = false;
    if (props.mode === 'create') {
        Object.assign(runtime, initData(props.type));
        if (globalStore.isOffLine) {
            runtime.resource = 'local';
        } else {
            searchAppList(null);
        }
    } else {
        searchAppList(props.appID);
        getRuntime(props.id);
    }
    extensions.value = '';
    open.value = true;
    listPHPExtensions();
};

watch(
    () => runtime.name,
    (newVal) => {
        if (newVal && mode.value == 'create') {
            runtime.params['CONTAINER_NAME'] = newVal;
        }
    },
    { deep: true },
);

defineExpose({
    acceptParams,
});
</script>

<style scoped>
.custom-link {
    color: var(--el-color-primary);
    cursor: pointer;
    text-decoration: underline;
    font-size: inherit;
    line-height: inherit;
}

.custom-link:hover {
    color: var(--el-color-primary-light-3);
}
</style>
